home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / snip1292.zip / LSD.C < prev    next >
C/C++ Source or Header  |  1992-12-26  |  7KB  |  266 lines

  1. /*
  2. ** LSD - A simple directory lister
  3. ** A public domain C demo program by Bob Stout
  4. */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. #include <dos.h>
  11.  
  12. /* For portability, make everything look like MSC 6 */
  13.  
  14. #if defined(__TURBOC__)
  15.  #include <dir.h>
  16.  #define _dos_findfirst(f,a,b) findfirst(f,b,a)
  17.  #define _dos_findnext(b) findnext(b)
  18.  #define find_t ffblk
  19.  #define _A_SUBDIR FA_DIREC
  20.  #define attrib ff_attrib
  21.  #define name ff_name
  22.  #define size ff_fsize
  23.  #define wr_time ff_ftime
  24.  #define wr_date ff_fdate
  25.  #define _dos_getdiskfree getdfree
  26.  #define diskfree_t dfree
  27.  #define avail_clusters df_avail
  28.  #define sectors_per_cluster df_sclus
  29.  #define bytes_per_sector df_bsec
  30. #else                   /* assume MSC/QC                                */
  31.  #include <errno.h>
  32. #endif
  33.  
  34. #ifdef TRUE
  35.  #undef TRUE
  36. #endif
  37. #ifdef FALSE
  38.  #undef FALSE
  39. #endif
  40. #ifdef ERROR
  41.  #undef ERROR
  42. #endif
  43.  
  44. enum LOGICAL {ERROR = -1, SUCCESS, FALSE = 0, TRUE};
  45.  
  46. #ifndef CAST
  47.  #define CAST(new_type,old_object) (*((new_type *)&(old_object)))
  48. #endif
  49.  
  50. #define LAST_CHAR(s) (((char *)s)[strlen(s) - 1])
  51.  
  52. struct DOS_TIME {
  53.         unsigned int ss : 5;
  54.         unsigned int mm : 6;
  55.         unsigned int hh : 5;
  56.         } ;
  57. #define dos_time(t) CAST(struct DOS_TIME, (t))
  58.  
  59. struct DOS_DATE {
  60.         unsigned int da : 5;
  61.         unsigned int mo : 4;
  62.         unsigned int yr : 7;
  63.         } ;
  64. #define dos_date(t) CAST(struct DOS_DATE, (t))
  65.  
  66. /*
  67. **  DOS DIR improved work-alike w/ improved formatting & attribute display
  68. **
  69. **  supports /W switch
  70. */
  71.  
  72. main(int argc, char *argv[])
  73. {
  74.       int i, files = 0, dirs = 0, argptr = 0, errflag = FALSE, cols, drive;
  75.       long siz_tot = 0L;
  76.       char *p, *fname, *ext, name[13], buf[67], numbuf[12];
  77.       struct find_t ff;
  78. #ifndef __ZTC__
  79.       struct diskfree_t df;
  80. #endif
  81.       int one_column(), five_column();
  82.       int (*display)(char *, char *, long, unsigned, unsigned, unsigned)
  83.             = one_column;
  84.       char *sprintfc(char *, long);
  85.       char *capitalize(const char *);
  86.  
  87.       strcpy(buf, fname = "*.*");
  88.       if(argc != 1)   for (i = 1; i < argc; ++i)
  89.       {
  90.             if ('/' == argv[i][0])
  91.             {
  92.                   if ('W' == toupper(argv[i][1]))
  93.                         display = five_column;
  94.                   else
  95.                   {
  96.                         puts("\aUsage: LSD [/W] [file]");
  97.                         errflag = TRUE;
  98.                   }
  99.             }
  100.             else if (!argptr)
  101.                   argptr = i;
  102.       }
  103.       if (argptr)
  104.       {
  105.             fname = argv[argptr];
  106.             strcpy(buf, fname);
  107.             if ('\\' == LAST_CHAR(buf) || ':' == LAST_CHAR(buf))
  108.                   strcat(buf, "*.*");
  109.             else
  110.             {
  111.                   if (SUCCESS == _dos_findfirst(buf, _A_SUBDIR, &ff))
  112.                   {
  113.                         if (ff.attrib & _A_SUBDIR && '.' != *ff.name)
  114.                         {
  115.                               if ('\\' != LAST_CHAR(buf))
  116.                                     strcat(buf, "\\");
  117.                               strcat(buf, "*.*");
  118.                         }
  119.                   }
  120.                   else  errflag = TRUE;
  121.             }
  122.       }
  123.       if (':' == buf[1])
  124.             drive = toupper(*buf) - '@';
  125.       else  drive = 0;
  126.       if (!errflag && !(_dos_findfirst(buf, 0xff, &ff))) do
  127.       {
  128.             siz_tot += ff.size;
  129.             if (ff.attrib & _A_SUBDIR)
  130.                   ++dirs;
  131.             else  ++files;
  132.             strcpy(name, ff.name);
  133.             if (NULL != (p = strchr(name, '.')) && p != name)
  134.             {
  135.                   *p  = '\0';
  136.                   ext = ++p;
  137.             }
  138.             else  ext = "";
  139.             cols = (*display)(name, ext, ff.size,
  140.                   ff.attrib, ff.wr_date, ff.wr_time);
  141.       } while (SUCCESS == _dos_findnext(&ff));
  142.       else
  143.       {
  144.             fprintf(stderr, "Cannot do directory on '%s'\n", fname);
  145.             exit(-1);
  146.       }
  147.       if (cols)
  148.             fputc('\n', stdout);
  149.       sprintfc(numbuf,siz_tot);
  150.       printf("\n%3d Files totalling %s bytes\n", files, numbuf);
  151.       printf("%3d Director%s\n", dirs, (1 == dirs) ? "y" : "ies");
  152. #ifndef __ZTC__
  153.       _dos_getdiskfree(drive, &df);
  154.       sprintfc(numbuf, (long)df.avail_clusters * df.sectors_per_cluster *
  155.             df.bytes_per_sector);
  156. #else /* if ZTC */
  157.       sprintfc(numbuf, dos_getdiskfreespace(drive));
  158. #endif
  159.       printf("%s bytes free\n", numbuf);
  160.       return 0;
  161. }
  162.  
  163. /*
  164. **  The single column directory entry display function
  165. */
  166.  
  167. int one_column(char    *name,
  168.                char    *ext,
  169.                long     size,
  170.                unsigned attribs,
  171.                unsigned date,
  172.                unsigned time)
  173. {
  174.       register int i, mask;
  175.       static char *atr = "RHSVDA", szbuf[12];
  176.  
  177.       sprintfc(szbuf, size);
  178.       printf("%-8s %-3s %12s  ", capitalize(name), capitalize(ext), szbuf);
  179.       for (i = 0, mask = 1; i < 6; ++i, mask <<= 1)
  180.       {
  181.             if (attribs & mask)
  182.                   fputc(atr[i], stdout);
  183.             else  fputc('.'   , stdout);
  184.       }
  185.       printf("%4d-%02d-%02d%4d:%02d:%02d\n",
  186.             dos_date(date).mo,
  187.             dos_date(date).da,
  188.             (dos_date(date).yr + 80) % 100,
  189.             dos_time(time).hh,
  190.             dos_time(time).mm,
  191.             dos_time(time).ss);
  192.       return 0;
  193. }
  194.  
  195. /*
  196. **  The five column directory entry display function
  197. */
  198.  
  199. int five_column(char    *name,
  200.                 char    *ext,
  201.                 long     size,
  202.                 unsigned attribs,
  203.                 unsigned date,
  204.                 unsigned time)
  205. {
  206.       static int cols = 0;
  207.  
  208.       printf("%-8s %-3s%s", capitalize(name), capitalize(ext),
  209.             (5 > ++cols) ? "    " : "");
  210.       if (0 == (cols %= 5))
  211.             putchar('\n');
  212.       return (cols);
  213. }
  214.  
  215. /*
  216. **  Display a long int using commas as thousands separators
  217. */
  218.  
  219. char *sprintfc(char *string, long num)
  220. {
  221.       if (num > 999999L)
  222.       {
  223.             sprintf(string, "%d,%03d,%03d",
  224.                   (int)(num / 1000000L),
  225.                   (int)((num % 1000000L) / 1000L),
  226.                   (int)(num % 1000L));
  227.       }
  228.       else
  229.       {
  230.             if (num > 999L)
  231.             {
  232.                   sprintf(string, "%d,%03d",
  233.                         (int)(num / 1000L),
  234.                         (int)(num % 1000L));
  235.             }
  236.             else  sprintf(string, "%d", (int)num);
  237.       }
  238.       return string;
  239. }
  240.  
  241. /*
  242. **  Capitalize a name or extension in place
  243. */
  244.  
  245. char *capitalize(const char *string)
  246. {
  247.       int flag = 0;
  248.       char *ptr = (char *)string;
  249.  
  250.       do
  251.       {
  252.             if (isalpha(*ptr))
  253.             {
  254.                   if (flag)
  255.                         *ptr = (char)tolower(*ptr);
  256.                   else
  257.                   {
  258.                         flag = 1;
  259.                         *ptr = (char)toupper(*ptr);
  260.                   }
  261.             }
  262.             else  flag = 0;
  263.       } while (*++ptr);
  264.       return (char *)string;
  265. }
  266.